package pe.com.bbva.pct.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

import pe.com.bbva.pct.messages.DelegadoErrorLazyDataModel;
import pe.com.bbva.pct.service.GeneralService;

public class TablaPaginador<T> extends LazyDataModel<T> {

	private static final long serialVersionUID = -720929384458886162L;
	private static final Logger log = Logger.getLogger(TablaPaginador.class);
	
	//private Method objetoMetodo;
	private String claseSource;
	private String metodoSource;
	private Object filtros;
	private int cantidadTotal;
	private DelegadoErrorLazyDataModel delegadoErrorLazyDataModel;
		
	public TablaPaginador(String data,String metodo,Object filtros,int cantidadTotal) {            
        this.filtros=filtros;
        this.cantidadTotal=cantidadTotal;
        this.claseSource=data;
        this.metodoSource=metodo;        		
    }
	
	public TablaPaginador(String data,String metodo,Object filtros,int cantidadTotal,
				DelegadoErrorLazyDataModel delegadoErrorLazyDataModel) {            
        this.filtros=filtros;
        this.cantidadTotal=cantidadTotal;
        this.claseSource=data;
        this.delegadoErrorLazyDataModel=delegadoErrorLazyDataModel;
        this.metodoSource=metodo;        		
    }
	
	public TablaPaginador(String data,Object filtros,int cantidadTotal) {            
        this.filtros=filtros;
        this.cantidadTotal=cantidadTotal;
        this.claseSource=data;
        this.metodoSource="";        		
    }
	
	public TablaPaginador(String data,Object filtros,int cantidadTotal,
				DelegadoErrorLazyDataModel delegadoErrorLazyDataModel) {            
        this.filtros=filtros;
        this.cantidadTotal=cantidadTotal;
        this.claseSource=data;
        this.delegadoErrorLazyDataModel=delegadoErrorLazyDataModel;
        this.metodoSource="";        		
    }
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters){		
		List<T> t=null;
		if (claseSource !=null){								
			if (metodoSource!=""){			
				Object objectoData=getDataSource(this.claseSource);	
				Class objectoClase=objectoData.getClass();									
				try {
					Method objetoMetodo = objectoClase.getDeclaredMethod(this.metodoSource, int.class,int.class,Object.class);
					t=(List<T>) objetoMetodo.invoke(objectoData,first,pageSize,filtros);
				} catch (NoSuchMethodException e) {		
					ejecutarDelegado(e);
				} catch (SecurityException e) {
					ejecutarDelegado(e);
				} catch (IllegalArgumentException e) {
					ejecutarDelegado(e);
				} catch (IllegalAccessException e) {
					ejecutarDelegado(e);
				} catch (InvocationTargetException e) {
					ejecutarDelegado(e);
				}
			}else{
				GeneralService generalService=(GeneralService)getDataSource(this.claseSource);	
				try {
					t=(List<T>)generalService.buscarObjetosPaginados(first, pageSize, filtros);
				} catch (Exception e) {
					ejecutarDelegado(e);
				}
			}
			this.setRowCount(cantidadTotal);
		}
		return t;
	}
	
	private Object getDataSource(String dataSource){
		return SpringJSFUtil.getBean(dataSource);
	}

	private void ejecutarDelegado(Exception e){
		if (this.delegadoErrorLazyDataModel!=null){
			delegadoErrorLazyDataModel.onError(e); 
		}
	}
}
